#include "metaconstructor.h"
#include "metainfo.h"
#include "reflectutils.h"

MetaConstructor::MetaConstructor(IMetaInfoBackend *meta, int idx)
{
	this->meta = meta ? meta->shared_from_this() : NULL;
	this->idx = idx;
}

MetaConstructor::MetaConstructor()
{
	idx = 0;
}

bool MetaConstructor::isValid() const
{
	return (bool)meta;
}

int MetaConstructor::Index() const
{
	return idx;
}

MetaInfo MetaConstructor::EnclosingMetaInfo() const
{
	return MetaInfo(meta.get());
}

std::string MetaConstructor::Signature() const
{
	if (!isValid()) {
		return "";
	}

	const auto & info = meta->GetConstructorInfo(idx);
	return ReflectUtils::GetSignature(meta->GetClassName(), info.ArgTypes);
}

std::vector<MetaTypeId> MetaConstructor::GetParamTypes() const
{
	if (!isValid()) {
		return std::vector<MetaTypeId>();
	}

	const auto & info = meta->GetConstructorInfo(idx);
	return	info.ArgTypes;
}

std::vector<std::string> MetaConstructor::GetConstructorInfos() const
{
	if (!isValid()) {
		return std::vector<std::string>();
	}

	const auto & info = meta->GetConstructorInfo(idx);

	return info.Infos;
}

void * MetaConstructor::DynamicCreate(void * buffer, const VariantList & param_)
{
	VariantList param = param_;
	const void* p[REX_MAX_PARAM_COUNT];
	void* ret = NULL;

	auto types = GetParamTypes();

	for (auto i = 0; i < types.size(); i++) {
		if (!(p[i] = Variant::BeReadyForParam(param[i], types[i]))) {
			return NULL;
		}
	}

	return CreateImply(buffer, p);
}

void * MetaConstructor::UnSafeCreate(void * buffer, const void ** param)
{
	return CreateImply(buffer, param);
}

void* MetaConstructor::CreateImply(void * buffer, const void ** param) const
{
	if (!isValid()) {
		return NULL;
	}

	if (buffer == NULL)
	{
		buffer = new char[meta->GetSize()];
	}

	meta->Create(buffer, idx, param);
	return buffer;
}
